﻿//-----------------------------------------------------------------------
// <copyright file="WorkerViewModel.cs" company="FER">
//     Copyright (c) All rights reserved.
// </copyright>
//-----------------------------------------------------------------------

namespace NMBP.View.ViewModel
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;

    using GalaSoft.MvvmLight;
    using GalaSoft.MvvmLight.Command;
    using GalaSoft.MvvmLight.Messaging;

    using NMBP.DAL;
    using NMBP.Models;
    using NMBP.ViewModels.Dialogs;

    /// <summary>
    /// Represents view model for WorkerWindow
    /// </summary>
    public class WorkerViewModel : ViewModelBase
    {
        #region Bindable fields

        /// <summary>
        /// Selected order in pending orders
        /// </summary>
        private Order selectedPendingOrder;

        /// <summary>
        /// Selected order in old orders
        /// </summary>
        private Order selectedOldOrder;

        /// <summary>
        /// List of pending orders
        /// </summary>
        private ObservableCollection<Order> pendingOrders;

        /// <summary>
        /// List of old orders
        /// </summary>
        private ObservableCollection<Order> oldOrders;

        /// <summary>
        /// List of order products
        /// </summary>
        private ObservableCollection<Product> selectedOrderProducts;

        /// <summary>
        /// Represents list of products for old order
        /// </summary>
        private ObservableCollection<Product> selectedOldOrderProducts;

        /// <summary>
        /// Action raised when view model needs to be initialized
        /// </summary>
        private Action<Worker> initWorkerViewModel;

        /// <summary>
        /// Represents selected supplier in combobox
        /// </summary>
        private Supplier selectedSupplier;

        /// <summary>
        /// List of all available suppliers
        /// </summary>
        private List<Supplier> availableSuppliers;

        /// <summary>
        /// Gets or sets a value indicating whether admin button is enabled
        /// </summary>
        private bool isAdminButtonEnabled;
        #endregion

        /// <summary>
        /// Worker recieved from login screen
        /// </summary>
        private Worker recievedWorker;

        /// <summary>
        /// Initializes a new instance of the WorkerViewModel class
        /// </summary>
        public WorkerViewModel()
        {
            this.initWorkerViewModel = new Action<Worker>(this.InitializeViewModel);
            Messenger.Default.Register<Worker>(this, "InitializeWorkerWindow", this.initWorkerViewModel);

            this.FinishOrder = new RelayCommand(
                () =>
                    {
                        if (this.SelectedPendingOrder == null)
                        {
                            this.DialogService.ShowMessage("Nije označeng nalog!", MessageType.ERROR);
                            return;
                        }

                        if (this.SelectedSupplier.Name == "-- Odaberite dobavljača --")
                        {
                            this.DialogService.ShowMessage("Nije odabran dobavljač za nalog!", MessageType.ERROR);
                            return;
                        }

                        var finishingOrder = this.SelectedPendingOrder;
                        this.PendingOrders.Remove(finishingOrder);
                        finishingOrder.SupplierName = this.SelectedSupplier.Name;
                        this.OldOrders.Add(finishingOrder);
                        this.SelectedPendingOrderProducts.Clear();
                        this.SelectedSupplier.IsActive = false;

                        var orderForSave = new Order 
                        { 
                            Cart = finishingOrder.Cart,
                            Code = finishingOrder.Code,
                            Date = finishingOrder.Date,
                            IsDone = true,
                            PaymentMethod = finishingOrder.PaymentMethod,
                            SupplierName = this.SelectedSupplier.Name,
                            WorkerUsername = this.recievedWorker.Username
                        };

                        this.DbFacade.SaveOrder(orderForSave);

                        this.DialogService.ShowMessage("Narudžba provedena.", MessageType.INFO);
                    });
            this.OpenAdmin = new RelayCommand(
                () => Messenger.Default.Send<Worker>(this.recievedWorker, "OpenAdminWindow"));
        }

        #region Binding commands
        /// <summary>
        /// Gets the command raised when finish pending order button is clicked
        /// </summary>
        public RelayCommand FinishOrder { get; private set; }

        /// <summary>
        /// Gets the command raised when open admin button is clicked
        /// </summary>
        public RelayCommand OpenAdmin { get; private set; }
        #endregion

        #region Bindable properties
        
        /// <summary>
        /// Gets or sets dialog service
        /// </summary>
        public IDialogService DialogService { get; set; }

        /// <summary>
        /// Gets or sets db facade
        /// </summary>
        public DbFacade DbFacade { get; set; }

        /// <summary>
        /// Gets or sets  Selected order in pending orders
        /// </summary>
        public Order SelectedPendingOrder
        {
            get
            {
                return this.selectedPendingOrder;
            }

            set
            {
                this.selectedPendingOrder = value;
                if (value != null)
                {
                    this.SelectedPendingOrderProducts.Clear();
                    foreach (var product in value.Cart.Products)
                    {
                        this.SelectedPendingOrderProducts.Add(product);
                    }
                }

                this.RaisePropertyChanged("SelectedPendingOrder");
            }
        }

        /// <summary>
        /// Gets or sets Selected order in old orders
        /// </summary>
        public Order SelectedOldOrder
        {
            get
            {
                return this.selectedOldOrder;
            }

            set
            {
                this.selectedOldOrder = value;
                if (value != null)
                {
                    this.SelectedOldOrderProducts.Clear();
                    foreach (var product in value.Cart.Products)
                    {
                        this.SelectedOldOrderProducts.Add(product);
                    }
                }

                this.RaisePropertyChanged("SelectedOldOrder");
            }
        }

        /// <summary>
        /// Gets or sets List of pending orders
        /// </summary>
        public ObservableCollection<Order> PendingOrders
        {
            get
            {
                return this.pendingOrders;
            }

            set
            {
                this.pendingOrders = value;
                this.RaisePropertyChanged("PendingOrders");
            }
        }

        /// <summary>
        /// Gets or sets List of old orders
        /// </summary>
        public ObservableCollection<Order> OldOrders
        {
            get
            {
                return this.oldOrders;
            }

            set
            {
                this.oldOrders = value;
                this.RaisePropertyChanged("OldOrders");
            }
        }

        /// <summary>
        /// Gets or sets List of order products for pending order
        /// </summary>
        public ObservableCollection<Product> SelectedPendingOrderProducts
        {
            get
            {
                return this.selectedOrderProducts;
            }

            set
            {
                this.selectedOrderProducts = value;
                this.RaisePropertyChanged("SelectedPendingOrderProducts");
            }
        }

        /// <summary>
        /// Gets or sets List of order products for old order
        /// </summary>
        public ObservableCollection<Product> SelectedOldOrderProducts
        {
            get
            {
                return this.selectedOldOrderProducts;
            }

            set
            {
                this.selectedOldOrderProducts = value;
                this.RaisePropertyChanged("SelectedOldOrderProducts");
            }
        }

        /// <summary>
        /// Gets or sets Represents selected supplier in combobox
        /// </summary>
        public Supplier SelectedSupplier
        {
            get
            {
                return this.selectedSupplier;
            }

            set
            {
                this.selectedSupplier = value;
                this.RaisePropertyChanged("SelectedSupplier");
            }
        }

        /// <summary>
        /// Gets or sets  List of all available suppliers
        /// </summary>
        public List<Supplier> AvailableSuppliers
        {
            get
            {
                return this.availableSuppliers;
            }

            set
            {
                this.availableSuppliers = value;
                this.RaisePropertyChanged("AvailableSuppliers");
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether admin button is enabled
        /// </summary>
        public bool IsAdminButtonEnabled
        {
            get
            {
                return this.isAdminButtonEnabled;
            }

            set
            {
                this.isAdminButtonEnabled = value;
                this.RaisePropertyChanged("IsAdminButtonEnabled");
            }
        }

        #endregion

        /// <summary>
        /// Initializes view model
        /// </summary>
        /// <param name="worker">Worker for initialization</param>
        private void InitializeViewModel(Worker worker)
        {
            if (this.DbFacade == null)
            {
                this.DbFacade = new DbFacade();
            }

            IsAdminButtonEnabled = worker.IsAdmin;

            this.DialogService = new DialogService();

            this.SelectedPendingOrderProducts = new ObservableCollection<Product>();
            this.PendingOrders = new ObservableCollection<Order>();

            this.OldOrders = new ObservableCollection<Order>();
            this.SelectedOldOrderProducts = new ObservableCollection<Product>();

            this.AvailableSuppliers = new List<Supplier>();
            this.AvailableSuppliers.Add(new Supplier { Name = "-- Odaberite dobavljača --" });
            this.SelectedSupplier = this.AvailableSuppliers[0];
            foreach (var supplier in this.DbFacade.GetSuppliers().Distinct().Where(supplier => this.AvailableSuppliers.FirstOrDefault(x => x.Name == supplier.Name) == null))
            {
                this.AvailableSuppliers.Add(supplier);
            }

            this.recievedWorker = worker;

            this.LoadPendingOrders();
            this.LoadOldOrders();
        }

        /// <summary>
        /// Loads pending orders
        /// </summary>
        private void LoadPendingOrders()
        {
            var pendingOrdersFromDb = this.DbFacade.GetPendingOrders();
            foreach (var order in pendingOrdersFromDb)
            {
                this.PendingOrders.Add(order);
            }
        }

        /// <summary>
        /// Loads old orders
        /// </summary>
        private void LoadOldOrders()
        {
            var oldOrdersFromDb = this.DbFacade.GetOldOrders();
            foreach (var order in oldOrdersFromDb)
            {
                this.OldOrders.Add(order);
            }
        }
    }
}
